<template>
  <div class="external-service-page">
    <!-- 加载状态 -->
    <div v-if="loading" class="loading">
      <!-- 加载动画或提示 -->
    </div>

    <!-- 错误状态 -->
    <div v-else-if="error" class="error">加载失败：{{ error }}</div>

    <!-- 数据展示 -->
    <div v-else class="data-container">
      <!-- 视图区第一部分：查询表单区域，分为两部分：默认展示查询条件区， 默认隐藏查询条件区-->
      <div class="search-form-wrapper">
        <el-form
          :inline="true"
          :model="searchForm"
          :rules="searchFormRules"
          class="search-form"
          ref="searchFormRef"
        >
          <!-- 默认展示查询条件区 -->
          <el-row :gutter="30">
            <!-- 动态渲染表单字段，遍历searchFormConfig -->
            <el-col
              :span="6"
              v-for="field in searchFormConfig"
              :key="field.queryAttributName"
            >
              <el-form-item
                :label="field.queryAttributLabel"
                :prop="field.queryAttributName"
              >
                <!-- 根据字段类型渲染不同的组件 -->
                <el-input
                  v-if="field.queryAttributType === 'input'"
                  v-model="searchForm[field.queryAttributName]"
                  :placeholder="field.queryAttributPlaceholder"
                  clearable
                />
                <el-date-picker
                  v-else-if="field.queryAttributType === 'date-picker'"
                  v-model="searchForm[field.queryAttributName]"
                  type="date"
                  :placeholder="field.queryAttributPlaceholder"
                  clearable
                />
                <el-select
                  v-else-if="field.queryAttributType === 'select'"
                  v-model="searchForm[field.queryAttributName]"
                  :placeholder="field.queryAttributPlaceholder"
                  clearable
                >
                  <el-option
                    v-for="option in field.options"
                    :key="option.value"
                    :label="option.label"
                    :value="option.value"
                  />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>

          <!-- 默认隐藏查询条件区 ，受按钮区的【展开】与【收起】按钮控制 -->
          <el-row v-if="isOpenHiddenSearchArea" :gutter="30">
            <el-col :span="6">
              <el-form-item label="日期">
                <el-date-picker
                  v-model="searchForm.date"
                  type="date"
                  placeholder="选择日期"
                  clearable
                />
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>

        <!-- 视图区第二部分，全局按钮区域 -->
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item>
              <el-button type="primary" @click="fetchListByButton"
                >查询</el-button
              >
              <el-button @click="reset">重置</el-button>
              <el-button
                type="danger"
                :disabled="selectedRows.length === 0"
                @click="handleBatchDelete"
                >批量删除</el-button
              >
              <!-- 选择勾选展示列弹框按钮 -->
              <el-button
                type="primary"
                @click="guiderColumnShowInTableDialogVisible = true"
                >选择列</el-button
              >
              <el-button
                class="toggle-btn"
                :class="{ hovered: isHovered }"
                @mouseenter="isHovered = true"
                @mouseleave="isHovered = false"
                @click="toggleAdvancedSearch"
              >
                <span>{{ isOpenHiddenSearchArea ? "收起" : "展开" }}</span>
                <el-icon>
                  <ArrowUp v-if="isOpenHiddenSearchArea" />
                  <ArrowDown v-else />
                </el-icon>
              </el-button>
            </el-form-item>
          </el-col>

          <!-- 选择勾选展示列弹框 -->
          <el-dialog
            v-model="guiderColumnShowInTableDialogVisible"
            title="选择列"
            width="30%"
          >
            <el-checkbox-group v-model="selectedColumns">
              <el-checkbox
                v-for="column in tableColumnList"
                :key="column.attributeName"
                :label="column.attributeName"
                :disabled="column.showRequired"
              >
                {{ column.attributeLabel }}
                <span v-if="column.showRequired" style="color: #f56c6c"
                  >（必选）</span
                >
              </el-checkbox>
            </el-checkbox-group>
            <template #footer>
              <el-button @click="guiderColumnShowInTableDialogVisible = false"
                >取消</el-button
              >
              <el-button type="primary" @click="updateVisibleColumns"
                >确定</el-button
              >
            </template>
          </el-dialog>
        </el-row>
      </div>

      <!-- 视图区第三部分：表格区域， 分为两部分：-->
      <div class="table-container">
        <el-table
          :data="tableData"
          :border="true"
          style="width: 100%; height: 635px"
          :row-class-name="tableRowClassName"
          @selection-change="handleSelectionChange"
        >
          <!-- 多选列 -->
          <el-table-column type="selection" width="55" />
          <el-table-column
            v-for="column in visibleColumns"
            :key="column.attributeName"
            :prop="column.attributeName"
            :label="column.attributeLabel"
            :width="column.columnWidth"
            :align="column.contentAlign"
            :sortable="column.isSortable"
            :formatter="column.formatterFunction"
            :fixed="column.fixedPosition"
          >
            <template #header>
              <!-- 如果 tooltip 不为空，则显示 tooltip -->
              <el-tooltip
                v-if="column.attributeTooltip"
                :content="column.attributeTooltip"
                placement="top"
              >
                <span>{{ column.attributeLabel }}</span>
              </el-tooltip>
              <!-- 如果 tooltip 为空，则直接显示表头文本 -->
              <span v-else>{{ column.attributeLabel }}</span>
            </template>
          </el-table-column>
          <el-table-column fixed="right" label="Operations" width="120">
            <template #default>
              <el-button link type="primary" size="small" @click="handleClick"
                >Detail</el-button
              >
              <el-button link type="primary" size="small">Edit</el-button>
            </template>
          </el-table-column>
        </el-table>
        <!-- 分页 -->
        <div class="pagination-wrapper">
          <el-pagination
            v-model:current-page="currentPage"
            v-model:page-size="pageSize"
            :page-sizes="[10, 20, 50]"
            :background="true"
            layout="total, sizes, prev, pager, next, jumper"
            :total="total"
            @current-change="fetchListByPage"
            @size-change="fetchListByPage"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, computed } from "vue";
import axios from "axios";
import { ElMessage, ElMessageBox } from "element-plus";

/**
 * 脚本第一部分，全局初始化。
 */
// 页面加载时自动调用
onMounted(() => {
  executeInitWhenFirstLoaded();
});

const loading = ref<boolean>(true);
const error = ref<string | null>(null);
// 标志变量，用于标记是否已经初始化
const isInitialized = ref<boolean>(false);

// 访问外部服务进行初始化,可以判断是否有权限访问。
const executeInitWhenFirstLoaded = async () => {
  if (isInitialized.value) return;
  try {
    const response = await axios.get(
      "/mock/api/web-display/main-display/getDisplayInfo"
    );
    if (response.data.result != true) {
      error.value = response.data.msg;
    }
    isInitialized.value = true;
  } catch (err) {
    error.value = (err as Error).message || "未知错误";
  } finally {
    loading.value = false;
  }
};

/**
 * 第二部分，定义查询框信息。
 */

// 查询表单属性定义
interface SearchFormFieldDefinition {
  /** 查询字段的名称，对应表单数据的键名。例如：`name`、`address`、`date` 等。 */
  queryAttributName: string;
  /** 查询字段的显示标签，用于表单中显示字段的名称。例如：`姓名`、`地址`、`日期` 等。 */
  queryAttributLabel: string;
  /** 查询字段的类型，用于确定渲染的表单组件类型。支持：`input`（文本输入框）、`date-picker`（日期选择器）、`select`（下拉选择框）。 */
  queryAttributType: string;
  /** 查询字段的占位符，用于在表单组件中显示提示文本。例如：`请输入姓名`、`选择日期` 等。 */
  queryAttributPlaceholder?: string;
  /** 查询字段的选项列表，仅当 `queryAttributType` 为 `select` 时有效。每个选项包含 `label`（显示文本）和 `value`（选项值）。 */
  options?: { label: string; value: any }[];
  /** 查询字段的校验规则，用于表单验证。每个规则是一个 `RuleItem` 对象。 */
  rules?: RuleItem[];
  /** 查询字段的默认值 */
  defaultValue?: any;
}

interface RuleItem {
  /** 是否必填。`true`：字段不能为空；`false`：字段可以为空。 */
  required?: boolean;
  /** 校验失败时的提示信息。例如：`姓名不能为空`。 */
  message?: string;
  /** 触发校验的时机。`blur`：字段失去焦点时触发；`change`：字段值改变时触发。 */
  trigger?: "blur" | "change";
  /** 字段的最小长度或最小值。字符串表示最小字符数，数字表示最小值。 */
  min?: number;
  /** 字段的最大长度或最大值。字符串表示最大字符数，数字表示最大值。 */
  max?: number;
  /** 字段的类型校验。支持：`string`、`number`、`boolean`、`method`、`regexp`、`integer`、`float`、`array`、`object`、`enum`、`date`、`url`、`hex`、`email`。 */
  type?:
    | "string"
    | "number"
    | "boolean"
    | "method"
    | "regexp"
    | "integer"
    | "float"
    | "array"
    | "object"
    | "enum"
    | "date"
    | "url"
    | "hex"
    | "email";
  /** 正则表达式校验。例如：`/^[A-Za-z]+$/` 表示只能输入字母。 */
  pattern?: RegExp;
  /** 自定义校验函数。`rule`：当前校验规则；`value`：字段的值；`callback`：校验完成后的回调函数。 */
  // eslint-disable-next-line
  validator?: (rule: any, value: any, callback: any) => void;
  /** 字段长度必须等于指定值。例如：`len: 5` 表示字段长度必须为 5。 */
  len?: number;
  /** 字段值必须在指定枚举值范围内。例如：`enum: ["Beijing", "Shanghai"]` 表示字段值只能是 `Beijing` 或 `Shanghai`。 */
  enum?: any[];
  /** 字段不能全是空白字符。`true`：字段不能全是空白字符；`false`：字段可以全是空白字符。 */
  whitespace?: boolean;
}

// 配置当前页面，具体查询框信息。 有两个方式，一个是从后台获取，一个是在当前页面直接定义，如下所示。
const searchFormConfig = ref<SearchFormFieldDefinition[]>([
  {
    queryAttributName: "name",
    queryAttributLabel: "姓名",
    queryAttributType: "input",
    queryAttributPlaceholder: "请输入姓名",
    rules: [{ required: true, message: "姓名不能为空", trigger: "blur" }],
  },
  {
    queryAttributType: "input",
    queryAttributLabel: "地址",
    queryAttributName: "address",
    queryAttributPlaceholder: "请输入地址",
  },
  {
    queryAttributType: "date-picker",
    queryAttributLabel: "日期",
    queryAttributName: "date",
    queryAttributPlaceholder: "选择日期",
  },
  {
    queryAttributType: "select",
    queryAttributLabel: "城市",
    queryAttributName: "city",
    queryAttributPlaceholder: "请选择城市",
    options: [
      { label: "北京", value: "Beijing" },
      { label: "上海", value: "Shanghai" },
      { label: "广州", value: "Guangzhou" },
      { label: "深圳", value: "Shenzhen" },
    ],
  },
]);

const generateRules = () => {
  const rules: Record<string, any> = {};
  searchFormConfig.value.forEach((field) => {
    if (field.rules) {
      rules[field.queryAttributName] = field.rules;
    }
  });
  return rules;
};

const searchFormRules = ref(generateRules());

// 查询表单数据
const searchForm = ref<Record<string, any>>({});

// 初始化 searchForm
searchFormConfig.value.forEach((field) => {
  searchForm.value[field.queryAttributName] = "";
});

/**
 * 第三部分，表格列信息定义。
 */

// 表格列信息接口定义
interface TableHeaderInterface {
  attributeName: string; // 列对应的数据字段名称，【必填】
  attributeLabel: string; // 列显示的标题文本，【必填】
  attributeTooltip?: string; // 列的提示文本，【可选】
  showRequired?: boolean; // 是否必须展示列标注， 默认非必须，都允许勾选与取消。
  defaultHidden?: boolean; // 是否默认隐藏，默认都展示，不隐藏。
  columnWidth?: number | string; // 列的宽度，可以是数字（如 180）或字符串（如 "180px"）
  contentAlign?: "left" | "center" | "right"; // 列内容的对齐方式，可选值为左对齐、居中对齐、右对齐
  isSortable?: boolean; // 是否允许列排序，默认【false】
  // eslint-disable-next-line
  formatterFunction?: (row: any) => string; // 自定义格式化函数，用于对列数据进行格式化处理
  fixedPosition?: "left" | "right"; // 列是否固定，可选值为左侧固定或右侧固定
  slotName?: string; // 自定义插槽的名称，用于支持更复杂的列内容渲染
}

// 表格列配置数据
const tableColumnList: TableHeaderInterface[] = [
  {
    attributeName: "date", // 列对应的数据字段名称
    attributeLabel: "日期", // 列显示的标题文本
    attributeTooltip: "用户的出生日期", // 用户的出生日期
    columnWidth: 180, // 列的宽度
    contentAlign: "center", // 列内容居中对齐
    isSortable: true, // 允许排序
  },
  {
    attributeName: "name", // 列对应的数据字段名称
    attributeLabel: "姓名", // 列显示的标题文本
    attributeTooltip: "身份证姓名", // 用户的出生日期
    columnWidth: 180, // 列的宽度
    contentAlign: "left", // 列内容左对齐
    formatterFunction: (row) => row.name.toUpperCase(), // 将姓名转为大写
  },
  {
    attributeName: "address", // 列对应的数据字段名称
    attributeLabel: "地址", // 列显示的标题文本
    fixedPosition: "right", // 固定在右侧
  },
];

// 选中的列（初始值为默认展示的列）
const selectedColumns = ref(
  tableColumnList
    .filter((column) => !column.defaultHidden || column.showRequired)
    .map((column) => column.attributeName)
);

// 可见的列
const visibleColumns = computed(() => {
  return tableColumnList.filter((column) =>
    selectedColumns.value.includes(column.attributeName)
  );
});
// 控制弹框显示
const guiderColumnShowInTableDialogVisible = ref(false);
// 更新可见列
const updateVisibleColumns = () => {
  guiderColumnShowInTableDialogVisible.value = false;
};

// 定义数据类型
interface TableData {
  date: string;
  name: string;
  address: string;
}
const tableData = ref<TableData[]>([]);

/***
 * 第4部分分页定义。
 */
// 分页相关
const currentPage = ref<number>(1);
const pageSize = ref<number>(10);
const total = ref<number>(0);

// 是否展开隐藏查询
const isOpenHiddenSearchArea = ref<boolean>(false);
const isHovered = ref<boolean>(false);

// 分页查询
const fetchListByPage = () => {
  fetchList(false);
};

// 表单按钮查询
const fetchListByButton = () => {
  currentPage.value = 1;
  fetchList(true);
};

// 获取 el-form 的引用
const searchFormRef = ref();

const fetchList = async (needCountTotal: boolean) => {
  try {
    // 校验表单
    await searchFormRef.value.validate();

    interface Params {
      [key: string]: any; // 允许任意字符串键和任意类型的值
    }

    const params: Params = {
      ...searchForm.value,
      pageNum: currentPage.value,
      pageSize: pageSize.value,
      needCountTotal,
    };

    // 过滤掉空值，一个复杂查询表单，有多个查询条件，查询时，往往大部分查询条件都是空，没有必要传递。
    const filteredParams = Object.keys(params).reduce((acc, key) => {
      const value = params[key];
      if (value !== null && value !== undefined && value !== "") {
        acc[key] = value;
      }
      return acc;
    }, {} as Record<string, any>);

    // 发送 POST 请求
    const response = await axios.post(
      "/web-display-demo/user/getUserList",
      filteredParams
    );

    // 处理响应数据
    if (response.data.result) {
      console.log("查询成功", response.data);
      tableData.value = response.data.rows; // 假设返回的数据在 response.data.rows 中
      total.value = response.data.total; // 假设返回的总数在 response.data.total 中
    } else {
      console.error("查询失败", response.data.msg);
    }
    // eslint-disable-next-line
  } catch (error) {}
};

// 处理表格行点击事件
const handleClick = () => {
  console.log("click");
};

// 重置
const reset = () => {
  Object.keys(searchForm.value).forEach((key) => {
    searchForm.value[key] = "";
  });
};

// 展示与关闭隐藏查询条件
const toggleAdvancedSearch = () => {
  isOpenHiddenSearchArea.value = !isOpenHiddenSearchArea.value;
};

// 表格行样式
const tableRowClassName = ({ rowIndex }: { rowIndex: number }) => {
  return rowIndex % 2 === 1 ? "success-row" : "";
};

// 存储用户选择的行数据
const selectedRows = ref<TableData[]>([]);

// 处理表格行选择事件
const handleSelectionChange = (rows: TableData[]) => {
  selectedRows.value = rows;
};

// 批量删除
const handleBatchDelete = async () => {
  if (selectedRows.value.length === 0) {
    ElMessage.warning("请选择要删除的数据");
    return;
  }

  try {
    // 确认删除
    await ElMessageBox.confirm("确定要删除选中的数据吗？", "提示", {
      type: "warning",
    });

    // 获取选中行的 ID 列表
    const ids = selectedRows.value.map((row) => row.address);

    // 发送删除请求
    // const response = await axios.post("/web-display-demo/user/batchDelete", {ids,});
    const response = await axios.post(
      "/mock/api/domain-address/user-view/batchDeleteUserList",
      { ids }
    );

    if (response.data.result) {
      ElMessage.success("删除成功");
      // 直接删除当前页面数据
      tableData.value = tableData.value.filter(
        (row) => !ids.includes(row.address)
      );
    } else {
      if (response.data.msg != null) {
        ElMessage.error(response.data.msg);
      } else {
        ElMessage.error("删除失败");
      }
    }
  } catch (err) {
    console.error("删除失败", err);
  }
};
</script>

<style scoped>
.external-service-page {
  height: 100%;
  display: flex;
  flex-direction: column;
  background-color: #f4f4f4;
}

.data-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 0;
  margin: 0;
}

.search-form-wrapper {
  background-color: white;
  padding: 15px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
  flex-shrink: 0;
}

.table-container {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
  background-color: white;
}

.pagination-wrapper {
  background-color: white;
  padding: 10px;
  box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
  text-align: center;
  flex-shrink: 0;
}

.toggle-btn {
  display: flex;
  align-items: center;
  gap: 5px;
  color: #409eff;
  border: 1px solid #dcdfe6;
  transition: all 0.3s ease-in-out;
}

.toggle-btn.hovered {
  color: #fff;
  background-color: #409eff;
  border-color: #409eff;
}

::v-deep(.el-table .success-row) {
  background-color: #fdf6ec !important;
}
</style>